<template>
  <div 
    ref="scrollContainer" 
    class="infinite-scroll-container"
    :class="{ 'loading-bottom': isLoading, 'loading-top': isLoadingTop }"
    @scroll="handleScroll"
    @touchstart="handleTouchStart"
    @touchmove="handleTouchMove"
    @touchend="handleTouchEnd"
  >
    <!-- 顶部加载指示器 -->
    <div v-if="isLoadingTop" class="loading-indicator top">
      <div class="loading-spinner"></div>
      <span>{{ loadingText || '加载中...' }}</span>
    </div>
    
    <!-- 内容插槽 -->
    <div class="scroll-content" ref="contentWrapper">
      <slot 
        :visibleItems="visibleItems" 
        :isLoading="isLoading || isLoadingTop" 
      />
    </div>
    
    <!-- 底部加载指示器 -->
    <div v-if="isLoading" class="loading-indicator bottom">
      <div class="loading-spinner"></div>
      <span>{{ loadingText || '加载中...' }}</span>
    </div>
    
    <!-- 无更多数据提示 -->
    <div v-if="!hasMore && items.length > 0" class="no-more-data">
      {{ noMoreDataText || '没有更多数据了' }}
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue'

// Props
const props = withDefaults(defineProps<{
  items: any[]
  itemHeight?: number
  bufferSize?: number
  preloadThreshold?: number
  loadingText?: string
  noMoreDataText?: string
  hasMore?: boolean
  direction?: 'vertical' | 'horizontal'
  virtualization?: boolean
}>(), {
  itemHeight: 280, // 默认卡片高度
  bufferSize: 3,   // 缓冲区大小
  preloadThreshold: 100, // 预加载阈值
  loadingText: '加载中...',
  noMoreDataText: '没有更多数据了',
  hasMore: true,
  direction: 'vertical',
  virtualization: true
})

// Emits
const emit = defineEmits<{
  'load-more': []
  'load-previous': []
}>()

// 响应式数据
const scrollContainer = ref<HTMLElement>()
const contentWrapper = ref<HTMLElement>()
const isLoading = ref(false)
const isLoadingTop = ref(false)
const startScrollY = ref(0)
const startScrollX = ref(0)
// lastScrollTime removed as it's not being used

// 虚拟滚动相关计算
const containerHeight = ref(0)
const containerWidth = ref(0)
const startIndex = ref(0)
const endIndex = ref(0)
// totalHeight removed as it's not being used
// offsetY removed as it's not being used

// 可见项目（虚拟滚动）
const visibleItems = computed(() => {
  if (!props.virtualization) {
    return props.items
  }
  
  // 计算可见区域内的项目
  const containerSize = props.direction === 'vertical' ? containerHeight.value : containerWidth.value
  const visibleCount = Math.ceil(containerSize / props.itemHeight) + props.bufferSize * 2
  
  if (props.direction === 'vertical' && scrollContainer.value) {
    const scrollTop = scrollContainer.value.scrollTop
    startIndex.value = Math.max(0, Math.floor(scrollTop / props.itemHeight) - props.bufferSize)
    endIndex.value = Math.min(
      props.items.length,
      startIndex.value + visibleCount
    )
  }
  
  return props.items.slice(startIndex.value, endIndex.value)
})

// 节流函数
const throttle = <T extends (...args: any[]) => any>(
  func: T,
  wait: number
): ((...args: Parameters<T>) => void) => {
  let timeout: ReturnType<typeof setTimeout> | null = null
  let previous = 0
  
  return function(...args: Parameters<T>) {
    const now = Date.now()
    const remaining = wait - (now - previous)
    
    if (remaining <= 0) {
      if (timeout) {
        clearTimeout(timeout)
        timeout = null
      }
      previous = now
      func(...args)
    } else if (!timeout) {
      timeout = setTimeout(() => {
        previous = Date.now()
        timeout = null
        func(...args)
      }, remaining)
    }
  }
}

// 处理滚动事件
const handleScroll = throttle(() => {
  if (!scrollContainer.value || isLoading.value) return
  
  const { scrollTop, scrollHeight, clientHeight, scrollLeft, scrollWidth, clientWidth } = scrollContainer.value
  
  // 检测底部加载
  const bottomThreshold = scrollHeight - clientHeight - props.preloadThreshold
  const rightThreshold = scrollWidth - clientWidth - props.preloadThreshold
  
  if (props.direction === 'vertical' && scrollTop >= bottomThreshold && props.hasMore) {
    loadMore()
  } else if (props.direction === 'horizontal' && scrollLeft >= rightThreshold && props.hasMore) {
    loadMore()
  }
  
  // 检测顶部加载（下拉刷新）
  if (props.direction === 'vertical' && scrollTop <= props.preloadThreshold && props.hasMore) {
    loadPrevious()
  } else if (props.direction === 'horizontal' && scrollLeft <= props.preloadThreshold && props.hasMore) {
    loadPrevious()
  }
}, 100)

// 触摸事件处理
const handleTouchStart = (e: TouchEvent) => {
  startScrollY.value = e.touches[0].clientY
  startScrollX.value = e.touches[0].clientX
}

const handleTouchMove = () => {
  // 可以在这里添加额外的触摸事件处理逻辑
}

const handleTouchEnd = () => {
  // 可以在这里添加触摸结束事件处理逻辑
}

// 加载更多数据
const loadMore = async () => {
  if (isLoading.value || !props.hasMore) return
  
  isLoading.value = true
  emit('load-more')
  
  // 模拟加载延迟，实际项目中应该在数据加载完成后设置isLoading为false
  setTimeout(() => {
    isLoading.value = false
  }, 1000)
}

// 加载上一页数据
const loadPrevious = async () => {
  if (isLoadingTop.value || !props.hasMore) return
  
  isLoadingTop.value = true
  emit('load-previous')
  
  // 模拟加载延迟
  setTimeout(() => {
    isLoadingTop.value = false
  }, 1000)
}

// 更新容器尺寸
const updateContainerSize = () => {
  if (scrollContainer.value) {
    containerHeight.value = scrollContainer.value.clientHeight
    containerWidth.value = scrollContainer.value.clientWidth
  }
}

// 监听窗口尺寸变化
const handleResize = throttle(() => {
  updateContainerSize()
}, 200)

// 监听数据变化
watch(() => props.items.length, () => {
  nextTick(() => {
    updateContainerSize()
  })
})

// 生命周期钩子
onMounted(() => {
  nextTick(() => {
    updateContainerSize()
  })
  window.addEventListener('resize', handleResize)
})

onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
})

// 提供方法给父组件
defineExpose({
  refresh: () => {
    isLoading.value = false
    isLoadingTop.value = false
    updateContainerSize()
  },
  scrollToTop: () => {
    if (scrollContainer.value) {
      scrollContainer.value.scrollTo({ top: 0, behavior: 'smooth' })
    }
  }
})
</script>

<style scoped>
.infinite-scroll-container {
  width: 100%;
  height: 100%;
  overflow-y: auto;
  overflow-x: hidden;
  position: relative;
  scroll-behavior: smooth;
}

.infinite-scroll-container.horizontal {
  overflow-x: auto;
  overflow-y: hidden;
  white-space: nowrap;
}

.scroll-content {
  min-height: 100%;
  position: relative;
}

/* 加载指示器 */
.loading-indicator {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 16px;
  color: #666;
  font-size: 14px;
  transition: opacity 0.3s ease;
}

.loading-indicator.top {
  border-bottom: 1px solid #eee;
}

.loading-indicator.bottom {
  border-top: 1px solid #eee;
}

/* 加载动画 */
.loading-spinner {
  width: 16px;
  height: 16px;
  border: 2px solid #f3f3f3;
  border-top: 2px solid #007AFF;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* 无更多数据提示 */
.no-more-data {
  text-align: center;
  padding: 20px;
  color: #999;
  font-size: 14px;
  border-top: 1px solid #eee;
}

/* 滚动条样式 */
.infinite-scroll-container::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

.infinite-scroll-container::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 3px;
}

.infinite-scroll-container::-webkit-scrollbar-thumb {
  background: #007AFF;
  border-radius: 3px;
}

.infinite-scroll-container::-webkit-scrollbar-thumb:hover {
  background: #0051D5;
}

/* 响应式调整 */
@media (max-width: 768px) {
  .loading-indicator {
    padding: 12px;
    font-size: 13px;
  }
  
  .loading-spinner {
    width: 14px;
    height: 14px;
  }
  
  .no-more-data {
    padding: 16px;
    font-size: 13px;
  }
}
</style>